home *** CD-ROM | disk | FTP | other *** search
/ BCI NET 2 / BCI NET 2.iso / archives / programming / source / graphicgems4.lha / GemsIV / minray / minray.c next >
Encoding:
C/C++ Source or Header  |  1995-02-06  |  2.2 KB  |  99 lines

  1. /* minimal ray tracer, hybrid version - 888 tokens
  2.  * Paul Heckbert, ucbvax!pixar!ph, 13 Jun 87
  3.  * Using tricks from Darwyn Peachey and Joe Cychosz. */
  4.  
  5. #define TOL 1e-7
  6. #define AMBIENT vec U, black, amb
  7. #define SPHERE struct sphere {vec cen, color; double rad, kd, ks, kt, kl, ir} \
  8.     *s, *best, sph[]
  9. typedef struct {double x, y, z} vec;
  10. #include "ray.h"
  11. yx;
  12. double u, b, tmin, sqrt(), tan();
  13.  
  14. double vdot(A, B)
  15. vec A, B;
  16. {
  17.     return A.x*B.x + A.y*B.y + A.z*B.z;
  18. }
  19.  
  20. vec vcomb(a, A, B)    /* aA+B */
  21. double a;
  22. vec A, B;
  23. {
  24.     B.x += a*A.x;
  25.     B.y += a*A.y;
  26.     B.z += a*A.z;
  27.     return B;
  28. }
  29.  
  30. vec vunit(A)
  31. vec A;
  32. {
  33.     return vcomb(1./sqrt(vdot(A, A)), A, black);
  34. }
  35.  
  36. struct sphere *intersect(P, D)
  37. vec P, D;
  38. {
  39.     best = 0;
  40.     tmin = 1e30;
  41.     s = sph+NSPHERE;
  42.     while (s-->sph)
  43.     b = vdot(D, U = vcomb(-1., P, s->cen)),
  44.     u = b*b-vdot(U, U)+s->rad*s->rad,
  45.     u = u>0 ? sqrt(u) : 1e31,
  46.     u = b-u>TOL ? b-u : b+u,
  47.     tmin = u>=TOL && u<tmin ?
  48.         best = s, u : tmin;
  49.     return best;
  50. }
  51.  
  52. vec trace(level, P, D)
  53. vec P, D;
  54. {
  55.     double d, eta, e;
  56.     vec N, color;
  57.     struct sphere *s, *l;
  58.  
  59.     if (!level--) return black;
  60.     if (s = intersect(P, D));
  61.     else return amb;
  62.  
  63.     color = amb;
  64.     eta = s->ir;
  65.     d = -vdot(D, N = vunit(vcomb(-1., P = vcomb(tmin, D, P), s->cen)));
  66.     if (d<0)
  67.     N = vcomb(-1., N, black),
  68.     eta = 1/eta,
  69.     d = -d;
  70.     l = sph+NSPHERE;
  71.     while (l-->sph)
  72.     if ((e = l->kl*vdot(N, U = vunit(vcomb(-1., P, l->cen)))) > 0 &&
  73.         intersect(P, U)==l)
  74.         color = vcomb(e, l->color, color);
  75.     U = s->color;
  76.     color.x *= U.x;
  77.     color.y *= U.y;
  78.     color.z *= U.z;
  79.     e = 1-eta*eta*(1-d*d);
  80.     /* the following is non-portable: we assume right to left arg evaluation.
  81.      * (use U before call to trace, which modifies U) */
  82.     return vcomb(s->kt,
  83.     e>0 ? trace(level, P, vcomb(eta, D, vcomb(eta*d-sqrt(e), N, black)))
  84.         : black,
  85.     vcomb(s->ks, trace(level, P, vcomb(2*d, N, D)),
  86.         vcomb(s->kd, color, vcomb(s->kl, U, black))));
  87. }
  88.  
  89. main()
  90. {
  91.     printf("%d %d\n", SIZE, SIZE);
  92.     while (yx<SIZE*SIZE)
  93.     U.x = yx%SIZE-SIZE/2,
  94.     U.z = SIZE/2-yx++/SIZE,
  95.     U.y = SIZE/2/tan(AOV/114.5915590261),    /* 360/PI~=114 */
  96.     U = vcomb(255., trace(DEPTH, black, vunit(U)), black),
  97.     printf("%.0f %.0f %.0f\n", U);        /* yowsa! non-portable! */
  98. }
  99.